---
type: tutorial
title: Send your first script to the browser
description: >-
  Tutorial: Build your first Astro blog —

  Add client-side interactivity to your mobile navigation with an Astro script
  tag
i18nReady: true
---
import Badge from '~/components/Badge.astro';
import Blanks from '~/components/tutorial/Blanks.astro';
import Box from '~/components/tutorial/Box.astro';
import Checklist from '~/components/Checklist.astro';
import MultipleChoice from '~/components/tutorial/MultipleChoice.astro';
import Option from '~/components/tutorial/Option.astro';
import PreCheck from '~/components/tutorial/PreCheck.astro';
import { Steps } from '@astrojs/starlight/components';

Let's add a hamburger menu to open and close your links on mobile screen sizes, requiring some client-side interactivity!

<PreCheck>
  - Create a hamburger menu component
  - Write a `<script>` to allow your site visitors to open and close the navigation menu
  - Move your JavaScript to its `.js` file
</PreCheck>

## Build a Hamburger component

Create a `<Hamburger />` component to open and close your mobile menu.

<Steps>
1. Create a file named `Hamburger.astro` in `src/components/`
  

2. Copy the following code into your component. This will represent your 3-line "hamburger" menu to open and close your navigation links on mobile. (You will add the new CSS styles to `global.css` later.)

    ```astro title="src/components/Hamburger.astro"
    --- 
    ---
    <div class="hamburger">
      <span class="line"></span>
      <span class="line"></span>
      <span class="line"></span>
    </div>
    ```

3. Place this new `<Hamburger />` component just before your `<Navigation />` component in `Header.astro`. 

    <details>
    <summary>Show me the code!</summary>

    ```astro title="src/components/Header.astro" ins={2,7}
    ---
    import Hamburger from './Hamburger.astro';
    import Navigation from './Navigation.astro';
    ---
    <header>
      <nav>
        <Hamburger />
        <Navigation />
      </nav>
    </header>
    ```
    </details>

4. Add the following styles for your Hamburger component:

    ```css title="src/styles/global.css" ins={2-13, 56-58}
    /* nav styles */
    .hamburger {
      padding-right: 20px;
      cursor: pointer;
    }

    .hamburger .line {
      display: block;
      width: 40px;
      height: 5px;
      margin-bottom: 10px;
      background-color: #ff9776;
    }

    .nav-links {
      width: 100%;
      top: 5rem;
      left: 48px;
      background-color: #ff9776;
      display: none;
      margin: 0;
    }

    .nav-links a {
      display: block;
      text-align: center;
      padding: 10px 0;
      text-decoration: none;
      font-size: 1.2rem;
      font-weight: bold;
      text-transform: uppercase;
    }

    .nav-links a:hover, a:focus {
      background-color: #ff9776;
    }

    .expanded {
      display: unset;
    }

    @media screen and (min-width: 636px) {
      .nav-links {
        margin-left: 5em;
        display: block;
        position: static;
        width: auto;
        background: none;
      }

      .nav-links a {
        display: inline-block;
        padding: 15px 20px;
      }

      .hamburger {
        display: none;
      }
    }
    ```
</Steps>


## Write your first script tag

Your header is not yet **interactive** because it can't respond to user input, like clicking on the hamburger menu to show or hide the navigation links. 

Adding a `<script>` tag provides client-side JavaScript to "listen" for a user event and then respond accordingly.

<Steps>
1. Add the following `<script>` tag to `index.astro`, just before the closing `</body>` tag.

    ```astro title="src/pages/index.astro" ins={2-6}
      <Footer />
      <script>
        document.querySelector('.hamburger').addEventListener('click', () => {
          document.querySelector('.nav-links').classList.toggle('expanded');
        });
      </script>
    </body>
    ```

2. Check your browser preview again at various sizes, and verify that you have a working navigation menu that is both responsive to screen size and responds to user input on this page.
</Steps>

### Importing a `.js` file

Instead of writing your JavaScript directly on each page, you can move the contents of your `<script>` tag into its own `.js` file in your project.

<Steps>
1. Create `src/scripts/menu.js` (you will have to create a new `/scripts/` folder) and move your JavaScript into it.

    ```js title="src/scripts/menu.js"
    document.querySelector('.hamburger').addEventListener('click', () => {
      document.querySelector('.nav-links').classList.toggle('expanded');
    });
    ```

2. Replace the contents of the `<script>` tag on `index.astro` with the following file import:

    ```astro title="src/pages/index.astro" ins={7} del={3-5}
      <Footer />
      <script>
        document.querySelector('.hamburger').addEventListener('click', () => {
          document.querySelector('.nav-links').classList.toggle('expanded');
        });

        import "../scripts/menu.js";
      </script>
    </body>
    ```

3. Check your browser preview again at a smaller size and verify that the hamburger menu still opens and closes your navigation links. 


4. Add the same `<script>` with import to your other two pages, `about.astro` and `blog.astro` and verify that you have a responsive, interactive header on each page.

    ```astro title="src/pages/about.astro & src/pages/blog.astro" ins={2-4}
      <Footer />
      <script>
        import "../scripts/menu.js";
      </script>
    </body>
    ```
</Steps>

:::note[Takeaway]
You had previously used some JavaScript to build parts of your site:

- Defining your page title and heading dynamically
- Mapping through a list of skills on the About page
- Conditionally displaying HTML elements

Those commands are all executed at build time to create static HTML for your site, and then the code is "thrown away." 

**The JavaScript in a `<script>` tag is sent to the browser**, and is available to run, based on user interactions like refreshing a page or toggling an input.
:::



<Box icon="question-mark">

### Test your knowledge

1. When does Astro run any JavaScript written in a component's frontmatter?
    <MultipleChoice>
      <Option>
       Astro never runs JavaScript
      </Option>
      <Option isCorrect>
        at build-time
      </Option>
      <Option>
         When a visitor clicks a button
      </Option>
    </MultipleChoice>

2. Optionally, Astro can send JavaScript to the browser to allow:
    <MultipleChoice>
      <Option>
        users to click page links
      </Option>
      <Option>
        faster load times
      </Option>
      <Option isCorrect>
        client-side interactivity
      </Option>
    </MultipleChoice>

3. The client-side JavaScript will be sent to a user’s browser when it is written or imported:
    <MultipleChoice>
      <Option isCorrect>
        in `<script>` tags
      </Option>
      <Option>
        between a `.astro` file's code fences
      </Option>
      <Option>
        in `global.css`
      </Option>
    </MultipleChoice>

</Box>

<Box icon="check-list">

## Checklist

<Checklist>
- [ ] I can add client-side interactivity with JavaScript in a `<script>` tag.
- [ ] I can import a `.js` file into a `<script>` tag.
</Checklist>

</Box>

### Resources

[Client-side scripts in Astro](/en/guides/client-side-scripts/)
